package controller

import (
	"context"
	"gin-service/lib/GinSrv/GinResp"
	"gin-service/lib/GinSrv/GinRouter"
	"gin-service/lib/MongoSrv"
	"gin-service/utils"
	"github.com/gin-gonic/gin"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

type Demo struct {
	Name string
	Age int
	Birthday string
	Permission []string
}

func WorkController(router GinRouter.Router) {
	routerCtx := context.Background()
	demoCollection := MongoSrv.Mongo().DB.Collection("demo")

	router.InitRouter()
	response := new(GinResp.RespImpl)

	router.Get("/select", func(ctx *gin.Context) {
		filter := bson.M{}

		queryName := ctx.Query("name")
		if queryName != "" {
			filter["name"] = queryName
		}

		ltAge := ctx.Query("lt_age")
		if ltAge != "" {
			filter["age"] = bson.M{"$lt": utils.STI(ltAge)}
		}

		lteAge := ctx.Query("lte_age")
		if lteAge != "" {
			filter["age"] = bson.M{"$lte": utils.STI(lteAge)}
		}

		gtAge := ctx.Query("gt_age")
		if gtAge != "" {
			filter["age"] = bson.M{"$gt": utils.STI(gtAge)}
		}

		gteAge := ctx.Query("gte_age")
		if gteAge != "" {
			filter["age"] = bson.M{"$gte": utils.STI(gteAge)}
		}

		findOptions := options.Find()
		findOptions.SetSort(bson.M{"age": -1})

		returnData := map[string]interface{}{}
		pagingQuery := ctx.Query("paging_query")
		if utils.STB(pagingQuery) {
			res := GinRouter.ThrowErrorReturn(demoCollection.CountDocuments(routerCtx, filter))
			count := res.(int64)
			returnData["count"] = count

			offset := utils.STI64(ctx.DefaultQuery("offset", "0"))
			findOptions.SetSkip(offset)

			limit := utils.STI64(ctx.DefaultQuery("limit", "8"))
			findOptions.SetLimit(limit)
		}

		res := GinRouter.ThrowErrorReturn(demoCollection.Find(routerCtx, filter, findOptions))
		cursor := res.(*mongo.Cursor)
		defer cursor.Close(routerCtx)

		var demoList []bson.M
		GinRouter.ThrowError(cursor.All(routerCtx, &demoList))

		if utils.STB(pagingQuery) {
			returnData["rows"] = demoList
			response.DataResp(ctx, returnData)
		} else {
			response.DataResp(ctx, demoList)
		}
	})

	router.Get("/select2", func(ctx *gin.Context) {
		filter := bson.M{}

		queryName := ctx.Query("name")
		if queryName != "" {
			filter["name"] = queryName
		}

		ltAge := ctx.Query("lt_age")
		if ltAge != "" {
			filter["age"] = bson.M{"$lt": utils.STI(ltAge)}
		}

		lteAge := ctx.Query("lte_age")
		if lteAge != "" {
			filter["age"] = bson.M{"$lte": utils.STI(lteAge)}
		}

		gtAge := ctx.Query("gt_age")
		if gtAge != "" {
			filter["age"] = bson.M{"$gt": utils.STI(gtAge)}
		}

		gteAge := ctx.Query("gte_age")
		if gteAge != "" {
			filter["age"] = bson.M{"$gte": utils.STI(gteAge)}
		}

		returnData := GinRouter.MongoQuery(ctx, "demo", filter, bson.M{"age": -1})
		response.DataResp(ctx, returnData)
	})

	router.Post("/insert", func(ctx *gin.Context) {
		//var demoBody Demo
		var demoBody bson.M
		GinRouter.ThrowError(ctx.BindJSON(&demoBody))

		/*insertData := bson.D{{
			"name",
			demoBody.Name,
		}, {
			"age",
			demoBody.Age,
		}, {
			"birthday",
			demoBody.Birthday,
		}}*/
		res := GinRouter.ThrowErrorReturn(demoCollection.InsertOne(routerCtx, demoBody))
		result := res.(*mongo.InsertOneResult)

		response.DataResp(ctx, result)
	})

	router.Post("/insertBatch", func(ctx *gin.Context) {
		//var demoBody []Demo
		var demoBody []bson.M
		GinRouter.ThrowError(ctx.BindJSON(&demoBody))

		insertLen := len(demoBody)
		insertArray := make([]interface{}, insertLen)

		for index, item := range demoBody {
			insertArray[index] = bson.D{{
				"name",
				item["name"],
			}, {
				"age",
				item["age"],
			}, {
				"birthday",
				item["birthday"],
			}}
		}

		res := GinRouter.ThrowErrorReturn(demoCollection.InsertMany(routerCtx, insertArray))
		result := res.(*mongo.InsertOneResult)

		response.DataResp(ctx, result)
	})

	router.Put("/update", func(ctx *gin.Context) {
		filter := bson.M{}

		queryName := ctx.Query("name")
		if queryName != "" {
			filter["name"] = queryName
		}

		var demoBody Demo
		GinRouter.ThrowError(ctx.BindJSON(&demoBody))

		updateData := bson.D{{
			"$set",
			bson.M{"age": demoBody.Age},
		}}

		res := GinRouter.ThrowErrorReturn(demoCollection.UpdateOne(routerCtx, filter, updateData))
		result := res.(*mongo.UpdateResult)

		response.DataResp(ctx, result)
	})
	
	router.Delete("/delete", func(ctx *gin.Context) {
		filter := bson.M{}

		queryName := ctx.Query("name")
		if queryName != "" {
			filter["name"] = queryName
		}

		ltAge := ctx.Query("lt_age")
		if ltAge != "" {
			filter["age"] = bson.M{"$lt": utils.STI(ltAge)}
		}

		lteAge := ctx.Query("lte_age")
		if lteAge != "" {
			filter["age"] = bson.M{"$lte": utils.STI(lteAge)}
		}

		gtAge := ctx.Query("gt_age")
		if gtAge != "" {
			filter["age"] = bson.M{"$gt": utils.STI(gtAge)}
		}

		gteAge := ctx.Query("gte_age")
		if gteAge != "" {
			filter["age"] = bson.M{"$gte": utils.STI(gteAge)}
		}

		if len(filter) == 0 {
			panic("any query required")
		}

		var demoData Demo
		GinRouter.ThrowError(demoCollection.FindOneAndDelete(routerCtx, filter).Decode(&demoData))

		response.DataResp(ctx, demoData)
	})

	router.Delete("/deleteBatch", func(ctx *gin.Context) {
		filter := bson.M{}

		queryName := ctx.Query("name")
		if queryName != "" {
			filter["name"] = queryName
		}

		ltAge := ctx.Query("lt_age")
		if ltAge != "" {
			filter["age"] = bson.M{"$lt": utils.STI(ltAge)}
		}

		lteAge := ctx.Query("lte_age")
		if lteAge != "" {
			filter["age"] = bson.M{"$lte": utils.STI(lteAge)}
		}

		gtAge := ctx.Query("gt_age")
		if gtAge != "" {
			filter["age"] = bson.M{"$gt": utils.STI(gtAge)}
		}

		gteAge := ctx.Query("gte_age")
		if gteAge != "" {
			filter["age"] = bson.M{"$gte": utils.STI(gteAge)}
		}

		if len(filter) == 0 {
			panic("any query required")
		}

		res := GinRouter.ThrowErrorReturn(demoCollection.DeleteMany(routerCtx, filter))
		result := res.(*mongo.DeleteResult)

		response.DataResp(ctx, result)
	})
}
